﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufBase.h"

class QXmlStreamReader;
class QXmlStreamWriter;
class QXmlStreamAttributes;
namespace gnuf {
    class GNUF_BASE_EXPORT Configuration
    {
    public:
        virtual ~Configuration();

    protected:
        Configuration();
        
        /// \brief Read the configuration file.
        /// \param fileName: The file name.
        /// \param isRelativePath: If true, the fileName only is a file name, and
        /// then wants to append a directory to compose a file path. If false, the
        /// fileName just is an absolute file path.
        /// \param isAtLocalAppData: If true, the file is at the local app data
        /// directory, and the isRelativePath always is true, regardless of the
        /// passed-in value. If false, the file is not there, and the isRelativePath
        /// works as normal.
        bool read(const std::wstring & fileName,
            const bool isRelativePath,
            const bool isAtLocalAppData = false);

        /// \brief Read the configuration form streamstring
        /// \param configStreamString configuration info
        /// \return 
        bool read(const std::wstring& configStreamString);

        /// \brief Write the configuration file.
        /// \param fileName: The file name.
        /// \param isRelativePath: If true, the fileName only is a file name, and
        /// then wants to append a directory to compose a file path. If false, the
        /// fileName just is an absolute file path.
        /// \param isAtLocalAppData: If true, the file is at the local app data
        /// directory, and the isRelativePath always is true, regardless of the
        /// passed-in value. If false, the file is not there, and the isRelativePath
        /// works as normal.
        bool write(const std::wstring & fileName,
            const bool isRalativePath,
            const bool isAtLocalAppData = false) const;

        /// \brief Let the derived class know before read really.
        /// \return Continue to read if return true. Stop if return false.
        virtual bool onPreRead() const { return true; }

        /// \brief Parse the elements in the xml.
        /// \param tokenType: Just QXmlStreamReader::TokenType.
        /// \param qtXmlReader: QXmlStreamReader.
        virtual void parseElement(int tokenType, const QXmlStreamReader & qtXmlReader) = 0;
        /// \brief Dump the elements in the xml.
        /// \param qtXmlWriter: QXmlStreamWriter.
        virtual void dumpElements(QXmlStreamWriter & qtXmlWriter) const {}
        
        /// \brief Parse the root.
        void parseRoot(const QXmlStreamAttributes &);
        /// \brief Dump the root.
        void dumpRoot(QXmlStreamWriter &) const;
        
    public:
        /// \return Return the directory in which the configurations are.
        static const std::wstring & directory();
        /// \return Return the Local AppData, which is the application temporary directory.
        static const std::wstring & localAppDataDirectory();
        /// \return Return the default directory.
        static std::wstring defaultDirectory();

        /// \brief Set the version.
        void setVersion(const std::string & val) { m_version = val;}
        /// \return Return the version.
        const std::string & version() const { return m_version; }

        /// \brief set version number for xml
        void setXmlVersion(const std::string& val) { m_xmlVersion = val; }

        /// \return Return version number for xml
        const std::string & xmlVersion() const { return m_xmlVersion; }
        
    protected:
        bool startRead(QXmlStreamReader& qtXmlReader);

    private:
        std::string m_xmlVersion;   // the version of the xml
        std::string m_version;      // the version of the configuration
        mutable bool m_rootTreated; // the root that was treated
    };
}
